
from gi.repository import Gtk, Gdk
from math import pi
import cairo

""" A module """

class Led(Gtk.DrawingArea):
    """ A Led is a single button that appears inside the grid. It mimes the
    behavior of a toggle button, but it's not a Gtk.ToggleButton since it's
    hard to change its theming while is much easier to extend a
    Gtk.DrawingArea. """
    BORDER = 1
    """ The amount of pixels that will be left void on each borders when the
    widget is drew. """

    def __init__(self):
        """Initialize a new Led."""
        Gtk.DrawingArea.__init__(self)
        self.neighbors = []
        """ Each Led has at least 2 neighbors and at most 4. Those are set by
        the Grid when the Grid itself it's created. When the Led is toggled, ie
        clicked by the user, then the Led and all'its neighbors get their
        ``active`` attribute negated. """
        self.mark = False
        """ If a Led is marked, then it will be drawn whit a cross on it by
        `_draw_callback`. This cross is meant to visually indicate the solution
        of the puzzle to the user. """
        self.active = False
        """ If the Led is active then is drawn whit a light color, otherwise a
        dark color is used"""
        self.connect('draw', self._draw_callback)

    def _draw_callback(self, widget, cairo_ctx):
        """ Callback invoked when the widget is drew. The gtk framework will
        take of calling the function. """
        # TODO move const outside
        # this routine is from
        # <http://cairographics.org/samples/rounded_rectangle/>
        border = self.BORDER
        allocation = self.get_allocation()
        width = allocation.width - border
        height = allocation.height - border
        radius = height / 19.0
        degrees = pi / 180.0;
        # choose what color should be used
        if self.active: cairo_ctx.set_source_rgb(1, 0.9, 0.8)
        else: cairo_ctx.set_source_rgb(0.6, 0.6, 1)
        cairo_ctx.new_sub_path ();
        cairo_ctx.arc(
            border + width - radius,
            border + radius,
            radius,
            -90 * degrees,
            0 * degrees)
        cairo_ctx.arc(
            border + width - radius,
            border + height - radius,
            radius,
            0 * degrees,
            90 * degrees)
        cairo_ctx.arc(
            border + radius,
            border + height - radius,
            radius,
            90 * degrees,
            180 * degrees)
        cairo_ctx.arc(
            border + radius,
            border + radius,
            radius,
            180 * degrees,
            270 * degrees)
        cairo_ctx.close_path()
        cairo_ctx.fill_preserve()
        cairo_ctx.set_source_rgb(0, 0, 0)
        cairo_ctx.set_line_width(1)
        cairo_ctx.stroke()
        if self.mark:
            cairo_ctx.move_to(0, 0)
            cairo_ctx.line_to(width, height)
            cairo_ctx.stroke()

    def clicked_callback(self):
        """ Callback invoked when the widget is clicked one single time. """
        self.active = not self.active
        # enshure the Led and its neighbors get immediatly re-drew
        self.queue_draw()
        for led in self.neighbors:
            led.active = not led.active
            led.queue_draw()
